﻿using Exhort.Configuration;
using Exhort.Dapper;
using Exhort.Entity;
using Exhort.Utility.Helper;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;

namespace Exhort.DbSet
{
    public partial class AffairContext : IDisposable
    {
        private static string dbConnString = ConfigHelper.GetByKey("database:connString");
        private static string dbProviderName = ConfigHelper.GetByKey("database:providerName");

        /// <summary>
        /// 私有上下文
        /// </summary>
        private EntitiesContext efContext = null;
        private DapperContext dapperContext = null;

        /// <summary>
        /// 事务控制
        /// </summary>
        private bool isTransaction = false;
        private bool dapperTransaction = false;

        /// <summary>
        /// 基础数据对象
        /// </summary>
        internal EntitiesContext Ef
        {
            get
            {
                if (efContext == null)
                {
                    efContext = new EntitiesContext(dbConnString, dbProviderName);
                }
                return efContext;
            }
        }

        /// <summary>
        /// 扩展数据对象
        /// </summary>
        internal DapperContext Dapper
        {
            get
            {
                if (dapperContext == null)
                {
                    dapperContext = new DapperContext(Ef.Connection);
                }

                if (isTransaction && !dapperTransaction)
                {
                    var transaction = Ef.Database.BeginTransaction();
                    dapperContext.BeginTransaction(transaction.GetDbTransaction());
                    dapperTransaction = true;
                }

                return dapperContext;
            }
        }

        /// <summary>
        /// 非事务提交
        /// </summary>
        /// <returns>受影响行数</returns>
        internal int NoTransactionCommit()
        {
            if (!isTransaction)
            {
                if (efContext != null)
                {
                    try
                    {
                        if (efContext.ChangeTracker.HasChanges())
                        {
                            return efContext.SaveChanges();
                        }
                    }
                    catch (Exception ex) { throw ex; }
                }
            }

            return 0;
        }

        #region DbSet

        /// <summary>
        /// 仓储缓存
        /// </summary>
        private Dictionary<Type, object> dbSetCache = new Dictionary<Type, object>();

        /// <summary>
        /// 数据操作对象
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="R">对象类型</typeparam>
        /// <returns></returns>
        private R DbSetByCache<T, R>()
            where T : BaseEntity, new()
            where R : BaseDbSet<T>, new()
        {
            if (!dbSetCache.ContainsKey(typeof(T)))
            {
                var dbSet = new R();
                // 设置上下文
                dbSet.Init(this);
                // 加入缓存中
                dbSetCache.Add(typeof(T), dbSet);

                return dbSet;
            }
            else { return (R)dbSetCache[typeof(T)]; }
        }

        /// <summary>
        /// 数据操作对象
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="R">对象类型</typeparam>
        /// <returns></returns>
        public R DbSet<T, R>()
            where T : BaseEntity, new()
            where R : BaseDbSet<T>, new()
        {
            return GetType().GetProperty(typeof(T).Name).GetValue(this, null) as R;
        }

        #endregion

        /// <summary>
        /// 开始事务
        /// </summary>
        public void BeginTransaction()
        {
            isTransaction = true;
        }

        /// <summary>
        /// 提交变更
        /// </summary>
        /// <returns>受影响行数</returns>
        public void Commit()
        {
            if (efContext != null)
            {
                try
                {
                    if (efContext.ChangeTracker.HasChanges())
                    {
                        efContext.SaveChanges();
                    }

                    if (dapperTransaction)
                    {
                        dapperContext.Commit();
                    }
                }
                catch (Exception ex)
                {
                    if (dapperTransaction)
                    {
                        dapperContext.Rollback();
                    }

                    throw ex;
                }
            }

            isTransaction = false; dapperTransaction = false;
        }

        #region 释放资源

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true); GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">是否释放</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (efContext != null)
                {
                    try
                    {
                        efContext.Dispose();
                        efContext = null;
                    }
                    catch { }
                }
                if (dapperContext != null)
                {
                    try
                    {
                        dapperContext.Dispose();
                        dapperContext = null;
                    }
                    catch { }
                }
            }
        }

        #endregion
    }
}